package org.kalai.unifypay.servlet;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.kalai.unifypay.Constant;
import org.kalai.unifypay.bean.Bizcnf;
import org.kalai.unifypay.bean.Member;
import org.kalai.unifypay.bean.MemberBiz;
import org.kalai.unifypay.bean.PartnerBiz;
import org.kalai.unifypay.bean.Transflow;
import org.kalai.unifypay.pay.Biz;
import org.kalai.unifypay.pay.BizFactory;
import org.kalai.unifypay.util.CommonUtil;
import org.kalai.unifypay.util.DataDao;
import org.kalai.unifypay.util.DateUtil;
import org.kalai.unifypay.util.StringUtil;

import com.alibaba.fastjson.JSON;
/**
 * 商户交易
 * @author zsl
 * @version 2016年9月11日 上午11:35:02
 */
@WebServlet(urlPatterns="/MemberTransaction")
public class MemberTransaction extends HttpServlet {
	private static final long serialVersionUID = -3589419678846874577L;
	private static final Logger logger = Logger.getLogger(MemberTransaction.class);
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		CommonUtil.responseObject(resp, Constant.ERROR_REQEST);
	}

	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		Map<String, String> param = CommonUtil.validate(request, response);
		if (param != null) {//验证通过 返回参数集合
			logger.info("接收到交易请求："+param);
			Map<String, Object> result = CommonUtil.createRespMap("10", "系统异常");
			try {
				String orderNo = param.get("orderNo");
				String subject = param.get("subject");
				String bizcode = param.get("bizcode");
				String memberNo = param.get("memberNo");
				String transAmt = param.get("transAmt");
				String bizData = param.get("bizData");
				String notifyUrl = param.get("notifyUrl");
				String partnerCode = request.getParameter("partnerCode");
				//判断参数非空
				if (StringUtil.isEmpty(orderNo, subject, bizcode, memberNo, transAmt)) {
					logger.error(String.format("业务参数错误：orderNo=%s, subject=%s, memberNo=%s, transAmt=%s", orderNo, subject, memberNo, transAmt));
					throw new RuntimeException("#200-业务参数错误");
				}
				//判断订单号是否重复
				Transflow transflows = DataDao.getInstance().getTransflowByOrderNo(memberNo,orderNo);
				if (transflows != null) {
					logger.error(String.format("订单号重复：orderNo=%s", orderNo));
					throw new RuntimeException("#213-订单号重复");
				}
				//判断平台业务通道状态
				Bizcnf bizcnf = DataDao.getInstance().getBizcnfByCode(bizcode);
				if (bizcnf == null || bizcnf.getStatus() != 1) {
					logger.error(String.format("业务通道关闭：bizcode=%s", bizcode));
					throw new RuntimeException("#203-业务通道关闭");
				}
				//判断D0交易时间 09:00-21:00
				if (bizcnf.getPattern() == 0) {
					int hours = Integer.valueOf(DateUtil.formatNow("HHmm"));
					if (hours < 900 || hours > 2059) {
						logger.error(String.format("该时间段不允许实时到账交易：bizcode=%s", bizcode));
						throw new RuntimeException("#203-该时间段不允许实时到账交易");
					}
				}
				//判断合作商通道状态
				PartnerBiz partnerBiz = DataDao.getInstance().getPartnerBiz(partnerCode, bizcode);
				if (partnerBiz == null || partnerBiz.getStatus() != 1) {
					logger.error(String.format("合作商通道关闭：partnerCode=%s, bizcode=%s", partnerCode, bizcode));
					throw new RuntimeException("#204-合作商通道关闭");
				}
				//判断商户状态
				Member member = DataDao.getInstance().getMember(memberNo);
				if (member == null) {
					logger.error(String.format("商户不存在：memberNo=%s", memberNo));
					throw new RuntimeException("#202-商户不存在");
				}
				if (member.getStatus() != 1) {
					logger.error(String.format("商户状态异常：memberNo=%s, status=%s", memberNo, member.getStatus()));
					throw new RuntimeException("#207-商户状态异常");
				}
				if(member.getAcctNo() == null){
					logger.error(String.format("商户未绑定银行卡：memberNo=%s", memberNo));
					throw new RuntimeException("#208-商户未绑定银行卡");
				}
				//判断商户业务权限
				MemberBiz memberBiz = DataDao.getInstance().getMerchantCode(memberNo, bizcode);
				if (memberBiz == null || memberBiz.getStatus() != 1) {
					logger.error(String.format("商户无此交易权限：memberNo=%s, bizcode=%s", memberNo, bizcode));
					throw new RuntimeException("#209-商户无此交易权限");
				}
				//生成订单号 并判断交易金额是否在允许范围内
				final String tranxSN = String.format("OR%s%s", DateUtil.formatNow("MMddHHmmssSSSS"), String.format("%04d", (int)(Math.random() * 100000)));
				//客户付款金额,单位分
				long cent = Long.valueOf(transAmt);
				if (cent < partnerBiz.getStart() * 100 || cent > partnerBiz.getEnd() * 100) {
					logger.error(String.format("商户交易金额不在允许范围内：memberNo=%s, bizcode=%s, transAmt=%s", memberNo, bizcode, cent));
					throw new RuntimeException("#210-商户交易金额不在允许范围内");
				}
				//计算手续费 四舍五入
				long transFee = new BigDecimal(cent * memberBiz.getRate() / 100.0).setScale(0, BigDecimal.ROUND_HALF_UP).longValue();
				String payAccount = "";
				/*商户编码为空则到合作方下轮循取*/
				String merchantCode=memberBiz.getMemberCode();
				if(StringUtil.isEmpty(merchantCode))
				{
				   merchantCode= DataDao.getInstance().getAlipayMerchantCode(partnerCode, bizcode.startsWith("20") ? 1 : 2);
				}
				//根据业务编码交易
				Biz biz = BizFactory.getBizByBizcode(bizcode);
				result = biz.pay(tranxSN, cent,  subject, notifyUrl, merchantCode, bizData);
				
				/*如果真实商户状态不可用则修改真实商户状态*/
				if("200103".equals(result.get("respCode")))
				{
				   DataDao.getInstance().updateMemberAlipayStatus(merchantCode,-1);
				}
				result.put("memberCode", merchantCode);
				result.put("tranxSN", tranxSN);
				result.put("orderNo", orderNo);
				//获取结算时间
				String settDate = CommonUtil.getSettDate(new Date(), bizcnf.getPattern() == 0);
				//获取无卡支付的信用卡号
				if (bizcode.startsWith("3")) {
					payAccount = JSON.parseObject(bizData).getString("acctNo");
				}
				//添加交易记录
				DataDao.getInstance().addMemberTransaction(
						tranxSN, orderNo, subject, bizcode, bizcnf.getPattern(), partnerCode, memberNo, cent, transFee, settDate, payAccount, result.get("respCode"), result.get("respDesc"), notifyUrl, 1);
				biz.afterPay(tranxSN, result.get("respCode").toString(), result.get("respDesc").toString(), transAmt);
			} catch (Exception e) {
				String message = e.getMessage();
				if (message != null && message.startsWith("#")) {
					result = CommonUtil.createRespMap(message.substring(1, message.indexOf("-")), message.substring(message.indexOf("-") + 1));
				} else {
					result = CommonUtil.createRespMap("10", "交易异常,请重新下单!");
					logger.error(param.get("orderNo")+"交易异常:", e); 
				}
			} finally {
				logger.info("交易返回："+result);
				CommonUtil.responseObject(response, JSON.toJSONString(result));
			}
		}
	}
}